﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;

namespace YanfengTestLibrary
{
	public class IdentityScope : IDisposable
	{
		// obtains user token   
		[DllImport("advapi32.dll", SetLastError = true)]
		private static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword,
		                                     int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

		// closes open handes returned by LogonUser   
		[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
		private static extern bool CloseHandle(IntPtr handle);

		[DllImport("Advapi32.DLL")]
		private static extern bool ImpersonateLoggedOnUser(IntPtr hToken);

		[DllImport("Advapi32.DLL")]
		private static extern bool RevertToSelf();

		private const int LOGON32_PROVIDER_DEFAULT = 0;
		private const int LOGON32_LOGON_NEWCREDENTIALS = 9; //域控中的需要用:Interactive = 2   
		private bool disposed;

		public IdentityScope(string sUsername, string sDomain, string sPassword)
		{
			// initialize tokens   
			IntPtr pExistingTokenHandle = new IntPtr(0);
			IntPtr pDuplicateTokenHandle = new IntPtr(0);

			try
			{
				// get handle to token   
				bool bImpersonated = LogonUser(sUsername, sDomain, sPassword,
				                               LOGON32_LOGON_NEWCREDENTIALS, LOGON32_PROVIDER_DEFAULT, ref pExistingTokenHandle);

				if (true == bImpersonated)
				{
					if (!ImpersonateLoggedOnUser(pExistingTokenHandle))
					{
						int nErrorCode = Marshal.GetLastWin32Error();
						throw new Exception("ImpersonateLoggedOnUser error;Code=" + nErrorCode);
					}
				}
				else
				{
					int nErrorCode = Marshal.GetLastWin32Error();
					throw new Exception("LogonUser error;Code=" + nErrorCode);
				}
			}
			finally
			{
				// close handle(s)   
				if (pExistingTokenHandle != IntPtr.Zero)
					CloseHandle(pExistingTokenHandle);
				if (pDuplicateTokenHandle != IntPtr.Zero)
					CloseHandle(pDuplicateTokenHandle);
			}
		}

		protected virtual void Dispose(bool disposing)
		{
			if (!disposed)
			{
				RevertToSelf();
				disposed = true;
			}
		}

		public void Dispose()
		{
			Dispose(true);
		}

		public static void  Test()
		{
			using (
			    IdentityScope iss =
			        new
			            IdentityScope("Administrator", "Shinetechina.com", "456a789+"))
			{
			File.Copy
					(@"D:\catChangesScripts.sql", @"\\10.10.50.24\New Folder\a.sql");
				Console.WriteLine("Ok");
			}
		}
	}

}
